#ifndef _OPCODE_HPP
#define _OPCODE_HPP
#include "Singleton.hpp"
#include <cassert>
#include <functional>
#include <unordered_map>
#include <memory>
#include <google/protobuf/message.h>
#include "WorldPacket.hpp"
class Opcode
{
public:
    typedef std::function<void(WorldPacket& packet)> OpcodeHandler;
private:
    friend class Singleton<Opcode>;
    Opcode()=default;
    ~Opcode()=default;
public:
    template<typename ProtoType>
    void RegisterProtocol(
        uint32_t protocol_id, 
        std::function<void(const ProtoType&)> concrete_handler) 
    {
        assert(_opcodes.find(protocol_id) == _opcodes.end());
        // 将具体协议类型的处理函数转换为通用Message处理函数
        _opcodes[protocol_id] = [concrete_handler](WorldPacket& packet) {
            ProtoType msg;
            // 类型安全检查
            if (msg.GetDescriptor() != ProtoType::descriptor()) {
                throw std::runtime_error("Protocol type mismatch!");
            }
            std::string bin((char*)packet.ReadBegin(), packet.ReadSize());
            msg.ParseFromString(bin);
            // 调用具体协议处理函数
            concrete_handler(msg);
        };
    }

    void Distribute(uint32_t opcode, WorldPacket& packet)
    {
        if(_opcodes.find(opcode) == _opcodes.end())
        {
            std::cout << "distribute not found opcode:" << opcode << std::endl;
            return;
        }
        _opcodes[opcode](packet);
    }
private:
    std::unordered_map<uint32_t, OpcodeHandler> _opcodes;
};

#define sOpcode Singleton<Opcode>::getInstance()
#define GetProtocolHandlerFunc(ProtocolId) sOpcode->GetHandler(ProtocolId)
#define RegisterProtoHandler(ProtocolId, ProtoType, Handler) sOpcode->RegisterProtocol<ProtoType>(static_cast<uint32_t>(ProtocolId), Handler);
#define DistributeProtoHandler(ProtocolId, WorldPacket) sOpcode->Distribute(ProtocolId, WorldPacket);
#endif